from APIConnection import APIConnection
import time

import threading
from CustomTask import CustomTask

class HopPath:
    a = APIConnection()
    
    def Id2Id_RId_Loop(self,id1,id2):
        result = []
        data1 = self.a.GetEntityById(id1)
        for i in data1['RId']:
            if i==id2:
                result = [id1,id2]
        return result                
         
    
    def Id2Id_RId_API(self,id1,id2):
        data = self.a.GetEntityByQuery("And(Id= %s, RId = %s)" % (id1,id2))
        if(len(data)==1):
            return [id1,id2]
        else:
            return []

    def Id2AuId_Id_API(self,ID,AuId):
        data = self.a.GetEntityByQuery("And(Id = %s, Composite(AA.AuId = %s))" %(ID, AuId))
        if(len(data)==1):
            return [ID, AuId]
        else:
            return []

    def Id2AuId_Id_Loop(self,ID,AuId):
        data = self.a.GetEntityById(ID)
        result = []
        for i in data.get('AA'):
            if i.get('AuId') == AuId:
                result = [ID, AuId]
        return result
    
    def AuId2Id_AuId_API(self,AuId,ID):
        query = "And(Id = %s,Composite(AA.AuId = %s))" % (ID,AuId)
        data = self.a.GetEntityByQuery(query)
        result = []
        if(len(data)==1):
            result = [AuId,ID]
        return result
    
    def AuId2Id_AuId_Loop(self,AuId,ID):
        data = self.a.GetEntityByAuId(AuId)
        result = []
        for i in data:
            if i['Id'] == ID:
                result = [AuId,ID]
        return result
        
    def AuId2AuId_AfId_Loop(self,AuId1,AuId2):
        result = []
        data1 = self.a.GetEntityByAuId(AuId1)
        data2 = self.a.GetEntityByAuId(AuId2)
        AfId1 = []
        AfId2 = []
        for item in data1:
            for i in item['AA']:
                if i['AuId'] == AuId1 and not(i.get('AfId') == None):
                    AfId1.append(i.get('AfId'))
        for item in data2:
            for i in item['AA']:
                if i['AuId'] == AuId1 and not(i.get('AfId') == None):
                    AfId2.append(i.get('AfId'))
        AfId_IN = list(set(AfId1)&set(AfId2))
        if(len(AfId_IN)>0):
            for i in AfId_IN:
                result.append([AuId1,i,AuId2])
        return result
        
    def Id2Id_FId_Loop(self,id1,id2):
        result = []
        data1 = self.a.GetEntityById(id1)
        data2 = self.a.GetEntityById(id2)
        FId1 = []
        FId2 = []
        for i in data1['F']:
            if not i.get('FId') in FId1: 
                FId1.append(i.get('FId'))
        for i in data2['F']:
            if not i.get('FId') in FId2: 
                FId2.append(i.get('FId'))
        tmp = [val for val in FId1 if val in FId2]
        if(len(tmp)>0):
            for i in tmp:
                result.append([id1,i,id2])
        return result
    
    def Id2Id_JId_Loop(self,id1,id2):
        result = []
        data1 = self.a.GetEntityById(id1)
        data2 = self.a.GetEntityById(id2)
        JId1 = data1['J'].get('JId')
        JId2 = data2['J'].get('JId')
        if(JId1 == JId2):
            result = [id1,JId1,id2]
        return result
        
    def Id2Id_CId_Loop(self,id1,id2):
        result = []
        data1 = self.a.GetEntityById(id1)
        data2 = self.a.GetEntityById(id2)
        CId1 = data1['C'].get('CId')
        CId2 = data2['C'].get('CId')
        if(JId1 == JId2):
            result = [id1,CId1,id2]
        return result
        
    def Id2ID_AuId_Loop(self,id1,id2):
        result = []
        data1 = self.a.GetEntityById(id1)
        data2 = self.a.GetEntityById(id2)
        AuId1 = []
        AuId2 = []
        for i in data1['AA']:
            if not i.get('AuId') in AuId1: 
                AuId1.append(i.get('AuId'))
        for i in data2['AA']:
            if not i.get('AuId') in AuId2: 
                AuId2.append(i.get('AuId'))
        tmp = [val for val in AuId1 if val in AuId2]
        if(len(tmp)>0):
            for i in tmp:
                result.append([id1,i,id2])
        return result
        
    def Id2AuId_RId(self,ID,AuId):
        result = []
        data1 = self.a.GetEntityById(ID)
        data2 = self.a.GetEntityByAuId(AuId)
        RId = []
        for i in data1['RId']:
            RId.append(i)
        Id_of_AuId =[]
        for i in data2:
            Id_of_AuId.append(i['Id'])
        tmp = [val for val in RId if val in Id_of_AuId]
        if(len(tmp)>0):
            for i in tmp:
                result.append([ID,i,AuId])
        return result
        
    def AuId2Id_RId(self,AuId,ID):
        '''
        AuId1->RId3->Id2
        Search IDs of AuId and match them with Id2's RId List 
        '''
        result = []
        data1=self.a.GetEntityById(ID)
        data2=self.a.GetEntityByAuId(AuId)
        RId = []
        for i in data1['RId']:
            RId.append(i)
        Id_of_AuId =[]
        for i in data2:
            Id_of_AuId.append(i['Id'])
        tmp = [val for val in Id_of_AuId if val in RId]
        if(len(tmp)>0):
            for i in tmp:
                result.append([AuId,i,ID])
        return result
    
    def AuId2AuId_Id_Id(self,AuId1,AuId2):
        '''
        AuId1->Id3->Id4->AuId2
        '''
        result = []
        data1 = self.a.GetEntityByAuId(AuId1)
        data2 = self.a.GetEntityByAuId(AuId2)
        Id3 = []
        Id4 = []
        for i in data2:
            Id4.append(i['Id'])
        for i in data1:
            Id3.append(i['Id'])
        print(len(Id3))
        print(len(Id4))
        start = time.time()
        args = [(i,j) for i in Id3 for j in Id4]
        index = 0
        tc = []
        MAX = float(len(args)/50)
        print MAX
        jndex = 0
        while(jndex<MAX):
            for arg in args[jndex*50:(jndex+1)*50]:
                ct = CustomTask(self.Id2Id_RId_Loop)
                tc.append(threading.Thread(target=ct.run,args=arg))
            for t in tc:
                index += 1
                t.start()
                print(index)
            for t in tc:
                t.join()
                index -= 1
                print(index)
            jndex += 1
            tc = []
        end=time.time()
        print(str(end-start))
        return result
        
    def Id2AuId_AuId_AfId(self,ID,AuId):
        '''
        Id1->AuId3->AfId4->AuId2
        Search the AuId3 which Id1 has and match with the target AuId2
        that with the same AfId4
        '''
        result = []
        data1 = self.a.GetEntityById(ID)
        AuId3 = []
        
        for i in data1.get('AA'):
            AuId3.append(i.get('AuId'))
        
        data2 = self.a.GetEntityByAuId(AuId)
        AfId4 = []
        for i in data2:
            for j in i.get('AA'):
                if(j.get('AfId') is not None):
                    AfId4.append(j.get('AfId'))
        AfId4 = list(set(AfId4))
        
        # args list of tuples
        args = [(x,y) for x in AuId3 for y in AfId4]
        
        # Init_query
        init_query = []
        for i in range(len(AuId3)):
            init_query.append("And(Composite(AA.AuId={0}),Composite(AA.AfId={1}))".format(args[i*len(AfId4)][0],args[i*len(AfId4)][1]))
        
        # build the api select query
        query=[]
        for i in range(len(AuId3)):
            for j in range(len(AfId4)-1):
                q = "And(Composite(AA.AuId={0}),Composite(AA.AfId={1}))".format(args[i*len(AfId4)+j+1][0],args[i*len(AfId4)+j+1][1])
                if(j==0):
                    union_q = "Or({0},{1})".format(init_query[i],q)
                else:
                    union_q = "Or({0},{1})".format(union_q,q)
            query.append(union_q)
            union_q=''

        for i in query:
            print i
        # get api data
        for i in query:
            try:
                Data = self.a.GetEntityByQuery(i);
                for j in Data:
                    for k in Data['AA']:
                        if k.get('AuId') == AuId3[i]:
                            for AfId in AfId4:
                                if k.get('AfId') == AfId:
                                    result.append([ID,k.get('AuId'),k.get('AfId'),AuId])
            except Exception as e:
                print("Throw Exception:{0},{1}".format(e.args[0],e.message))
            finally:
                result = []            
        return result
        
        
if __name__ == "__main__":
    path = HopPath()
    result = path.AuId2Id_AuId_Loop(2223355696,2041325010)
    print("result="+repr(result))
